home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / PickOne / sources / PickOne_document.c next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  15.0 KB  |  606 lines  |  [TEXT/CWIE]

  1. /*  PickOne_document.c                                                                            
  2.  
  3.     This contains all the document-specific code.
  4.                                                                                     
  5.     Michael Bishop - August 21 1996                                                    
  6.     Nick Thompson
  7.     Robert Dierkes
  8.     Scott Kuechle - March 1997                                                                                
  9.     (c)1994-97 Apple computer Inc., All Rights Reserved                                
  10.  
  11. */
  12.  
  13.  
  14. /* --------------------------------------------------------------------
  15. ** Includes
  16. */
  17. #include    <Quickdraw.h>    /*    For Show/HideCursor routines    */
  18. #include    <assert.h>
  19.  
  20. #include    "PickOne_document.h"
  21. #include    "PickOne_documentStructure.h"
  22.  
  23. #include    "PickOne_Support.h"
  24. #include    "PickOne_window.h"
  25. #include    "PickOne_utility.h"
  26.  
  27. #include    "PictRead.h"
  28.  
  29.  
  30. /* QuickDraw 3D stuff */
  31. #include    "QD3DMath.h"
  32. #include    "QD3DCamera.h"
  33. #include    "QD3DTransform.h"
  34. #include    "QD3DGroup.h"
  35. #include    "QD3DShader.h"
  36. #include    "QD3DStorage.h"
  37. #include    "QD3DIO.h"
  38. #include    "QD3DPick.h"
  39. #include    "QD3DRenderer.h"
  40. #include    "QD3DAcceleration.h"
  41.  
  42.  
  43. /* --------------------------------------------------------------------
  44. ** Local Functions
  45. */
  46. static    void            Document_Init( DocumentHdl theDocument) ;
  47. static    unsigned long    Document_DoPick( DocumentPtr theDocument, TQ3PickObject    pickObject);
  48. static    TQ3PickObject    Document_NewPick(TQ3WindowPointPickData    *pWPPData);
  49.  
  50. /* -------------------------------------------------------------------------------------------
  51. **    Document_New
  52. **    Loads a new Document with a blank (white) canvas for a texture
  53. */
  54.  
  55. DocumentHdl Document_New(void)
  56. {
  57.     DocumentHdl theDocument = (DocumentHdl)NewHandle( sizeof(DocumentRec)) ;
  58.     
  59.     if( theDocument != NULL )
  60.     {
  61.         Document_Init(theDocument);
  62.         
  63.         /*    Get a window for it    */
  64.         (**theDocument).fWindow = Window_New();
  65.         if ((**theDocument).fWindow == NULL) goto bail;
  66.         
  67.         /* store a reference to the document record in the window's refcon */
  68.         Window_SetDocument((**theDocument).fWindow, theDocument ) ;
  69.         
  70.         /*  sets up the 3d data for the scene */
  71.         /*  Create view for QuickDraw 3D. */
  72.         (**theDocument).fView = MyNewView( (**theDocument).fWindow ) ;
  73.         if ((**theDocument).fView == NULL) {    BP_DebugString("View could not be created!");
  74.                                                 goto bail;    }
  75.         
  76.         /*  the main display group: */
  77.         (**theDocument).fModel = MyNewModel(theDocument) ;
  78.         if ((**theDocument).fModel == NULL) goto bail;
  79.     
  80.         /*  the drawing styles: */
  81.         (**theDocument).fInterpolation =
  82.                 Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
  83.         if ((**theDocument).fInterpolation == NULL) goto bail;
  84.         
  85.         (**theDocument).fBackFacing =
  86.                 Q3BackfacingStyle_New(kQ3BackfacingStyleRemove ) ;
  87.         if ((**theDocument).fBackFacing == NULL) goto bail;
  88.         
  89.         (**theDocument).fFillStyle =
  90.                 Q3FillStyle_New(kQ3FillStyleFilled ) ;
  91.         if ((**theDocument).fFillStyle == NULL) goto bail;
  92.  
  93.     }
  94.     return theDocument ;
  95. bail:
  96.     Document_Dispose(theDocument);
  97.     theDocument = NULL;
  98.     return theDocument;
  99. }
  100.  
  101. /* -------------------------------------------------------------------------------------------
  102. ** Document_Dispose
  103. ** Destroys and deletes all the data in a document
  104. */
  105.  
  106. void Document_Dispose( DocumentHdl theDocument)
  107. {
  108.     assert(theDocument != NULL);
  109.     assert(*theDocument != NULL);
  110.     
  111.     if ((**theDocument).fView != NULL)
  112.         Q3Object_Dispose((**theDocument).fView) ;
  113.         
  114.     if ((**theDocument).fModel != NULL)
  115.         Q3Object_Dispose((**theDocument).fModel) ;
  116.         
  117.     if ((**theDocument).fInterpolation != NULL)
  118.         Q3Object_Dispose((**theDocument).fInterpolation) ;
  119.         
  120.     if ((**theDocument).fBackFacing != NULL)
  121.         Q3Object_Dispose((**theDocument).fBackFacing) ;
  122.         
  123.     if ((**theDocument).fFillStyle != NULL)
  124.         Q3Object_Dispose((**theDocument).fFillStyle) ;
  125.     
  126.     if ((**theDocument).fWindow != NULL)
  127.         Window_Dispose ( (**theDocument).fWindow ) ;
  128.  
  129.     /*    Do this last    */
  130.     DisposeHandle( (Handle)theDocument ) ;
  131. }
  132.  
  133.  
  134.  
  135. /* -------------------------------------------------------------------------------------------
  136. **    Document_GetCamera
  137. **    Returns the Camera associated with the document
  138. */
  139. TQ3CameraObject        Document_GetCamera(DocumentHdl    theDocument)
  140. {
  141.     TQ3CameraObject    theCamera;
  142.     
  143.     assert(theDocument != NULL);
  144.     assert(*theDocument != NULL);
  145.     
  146.     Q3View_GetCamera((**theDocument).fView, &theCamera);
  147.     
  148.     return theCamera;
  149. }
  150.  
  151.  
  152. /* -------------------------------------------------------------------------------------------
  153. **    Document_GetRendererPreferences
  154. **    Returns the Renderer Preferences associated with the document
  155. */
  156. TQ3Status    Document_GetRendererPreferences(DocumentHdl    theDocument,
  157.                                             long        *theVendorID,
  158.                                             long        *theEngineID)
  159. {
  160.     TQ3RendererObject    theRenderer;
  161.     TQ3Status            theStatus = kQ3Success;
  162.     
  163.     assert(theDocument != NULL);
  164.     assert(*theDocument != NULL);
  165.     
  166.     if (Q3View_GetRenderer((**theDocument).fView, &theRenderer) != kQ3Failure)
  167.     {
  168.         if (Q3Renderer_GetType(theRenderer) == kQ3RendererTypeInteractive)
  169.             Q3InteractiveRenderer_GetPreferences(theRenderer, theVendorID, theEngineID);
  170.         else theStatus = kQ3Failure;
  171.         
  172.         Q3Object_Dispose(theRenderer);
  173.         
  174.     } else theStatus = kQ3Failure;
  175.     
  176.     return theStatus;
  177. }
  178.  
  179. /* -------------------------------------------------------------------------------------------
  180. **    Document_SetRendererPreferences
  181. **    Sets the Renderer Preferences
  182. */
  183. TQ3Status    Document_SetRendererPreferences(DocumentHdl    theDocument,
  184.                                             long        theVendorID,
  185.                                             long        theEngineID)
  186. {
  187.     TQ3RendererObject    theRenderer;
  188.     TQ3Status            theStatus = kQ3Success;
  189.     
  190.     assert(theDocument != NULL);
  191.     assert(*theDocument != NULL);
  192.     
  193.     if (Q3View_GetRenderer((**theDocument).fView, &theRenderer) != kQ3Failure)
  194.     {
  195.         if (Q3Renderer_GetType(theRenderer) == kQ3RendererTypeInteractive)
  196.         {
  197.             Q3InteractiveRenderer_SetPreferences(theRenderer, theVendorID, theEngineID);
  198.             Q3View_SetRenderer((**theDocument).fView, theRenderer);
  199.         }
  200.         else theStatus = kQ3Failure;
  201.         
  202.         Q3Object_Dispose(theRenderer);
  203.         
  204.     } else theStatus = kQ3Failure;
  205.     
  206.     
  207.     return theStatus;
  208. }
  209.  
  210. /* -------------------------------------------------------------------------------------------
  211. **    Document_Open
  212. **    Loads a new Document with a Pict for a texture
  213. */
  214.  
  215. TQ3Status Document_Open(DocumentHdl theDocument)
  216. {    
  217.     assert(theDocument != NULL);
  218.     assert(*theDocument != NULL);
  219.     
  220.     return kQ3Failure;    
  221.     
  222. }
  223.  
  224.  
  225. /* -------------------------------------------------------------------------------------------
  226. **    Document_Save
  227. **    Saves the *Model*
  228. */
  229.  
  230. TQ3Status Document_Save(DocumentHdl    theDocument)
  231. {
  232.     assert(theDocument != NULL);
  233.     assert(*theDocument != NULL);
  234.     
  235.     /*    If you can figure out how to save the model,
  236.         This is a good place to put in that code    */
  237.     theDocument;    /*    in the meantime, no op    */
  238.     return kQ3Failure;
  239. }
  240.     
  241. /* -------------------------------------------------------------------------------------------
  242. **    Document_Draw
  243. **    Draws the document in the current DrawContext
  244. */
  245.  
  246. TQ3Status Document_Draw( DocumentPtr theDocument )
  247. {    
  248.     TQ3Status        status = kQ3Failure;
  249.     
  250.     assert(theDocument != NULL);
  251.     
  252.     if ((status = Q3View_StartRendering(theDocument->fView)) != kQ3Failure)
  253.     do {
  254.         Document_SubmitScene( theDocument ) ;
  255.     } while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );
  256.     
  257. bail:
  258.     
  259.     return status ;
  260.  
  261. }
  262.  
  263.  
  264.  
  265. /* -------------------------------------------------------------------------------------------
  266. **    Document_SubmitScene
  267. **    if you make a function like this, you can easily use it inside a
  268. **    Rendering or Picking or BoundingSphere/Box loop
  269. **    (See Document_Draw)
  270. */
  271.  
  272. TQ3Status Document_SubmitScene( DocumentPtr theDocument ) 
  273. {        
  274.     TQ3Status    theStatus = kQ3Success;
  275.  
  276.     
  277.     assert(theDocument != NULL);
  278.     
  279.     /*
  280.      *    Interpolation
  281.      */
  282.     if (Q3Style_Submit(    theDocument->fInterpolation,
  283.                         theDocument->fView) == kQ3Failure)
  284.         theStatus = kQ3Failure;
  285.         
  286.     /*
  287.      *    BackFacing
  288.      */
  289.     if (Q3Style_Submit(    theDocument->fBackFacing ,
  290.                         theDocument->fView) == kQ3Failure)
  291.         theStatus = kQ3Failure;
  292.         
  293.     /*
  294.      *    FillStyle
  295.      */
  296.     if (Q3Style_Submit(    theDocument->fFillStyle,
  297.                         theDocument->fView) == kQ3Failure)
  298.         theStatus = kQ3Failure;
  299.         
  300.     /*
  301.      *    Model
  302.      */
  303.  
  304.     if (Q3DisplayGroup_Submit(    theDocument->fModel,
  305.                                 theDocument->fView) == kQ3Failure)
  306.         theStatus = kQ3Failure;
  307.  
  308. bail:
  309.  
  310.     return kQ3Success ;
  311. }
  312.  
  313.  
  314.  
  315.  
  316. /* -------------------------------------------------------------------------------------------
  317. ** Document_Idle
  318. ** Does the Idle Action
  319. */
  320. void    Document_Idle(DocumentHdl theDocument)
  321. {
  322.     TQ3Matrix4x4        tmp;
  323.     
  324.     assert(theDocument != NULL);
  325.     assert(*theDocument != NULL);
  326.         
  327.     /*    For now, this just rotates the model    */
  328.  
  329.     Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.025, 0.03, 0.02);
  330.     Q3Matrix4x4_Multiply(&(**theDocument).fRotation, &tmp, &(**theDocument).fRotation);
  331.                             
  332.     HLock( (Handle)theDocument  ) ;
  333.     
  334.     Document_Draw(*theDocument);
  335.  
  336.     HUnlock( (Handle)theDocument  ) ;
  337. }
  338.  
  339.  
  340. /* -------------------------------------------------------------------------------------------
  341. ** Document_Init
  342. ** Sets All Variables and objects common to all documents
  343. */
  344.  
  345. void Document_Init( DocumentHdl theDocument) 
  346. {
  347.     assert(theDocument != NULL);
  348.     assert(*theDocument != NULL);
  349.         
  350.     /*    NULL out all of the parameters    */
  351.     /*    Check out the header file for the parameter comments    */
  352.     (**theDocument).fWindow = NULL ;
  353.     
  354.     (**theDocument).fView = NULL;
  355.     (**theDocument).fModel = NULL ;
  356.     (**theDocument).fInterpolation = NULL ;
  357.     (**theDocument).fBackFacing = NULL ;
  358.     (**theDocument).fFillStyle = NULL ;
  359.     Q3Matrix4x4_SetIdentity(&(**theDocument).fRotation);
  360.  
  361. }
  362.  
  363.  
  364.  
  365. /*
  366.  *    Document_DoPick
  367.  *
  368.  *    Submits objects for picking and returns the number of objects hit.
  369.  *
  370.  *    This should be identical to DrawDocumentData.
  371.  */
  372. static
  373. unsigned long Document_DoPick(
  374.     DocumentPtr        pDocument,
  375.     TQ3PickObject    pickObject)
  376. {
  377.     TQ3ViewObject    aView;
  378.     TQ3ViewStatus    viewStatus;
  379.     unsigned long    numHits;
  380.  
  381.     assert(pDocument != NULL);
  382.     
  383.     aView   = pDocument->fView;
  384.     numHits = 0;
  385.  
  386.     if (Q3View_StartPicking(aView, pickObject) == kQ3Success) {
  387.         do {
  388.             Document_SubmitScene( pDocument ) ;
  389.  
  390.             viewStatus = Q3View_EndPicking(aView);
  391.  
  392.         } while (viewStatus == kQ3ViewStatusRetraverse);
  393.  
  394.         if (viewStatus == kQ3ViewStatusDone) {
  395.             Q3Pick_GetNumHits(pickObject, &numHits);
  396.         }
  397.         else {
  398.              BP_DebugString("Document_DoPick: Q3View_EndPicking failed.");
  399.         }
  400.     }
  401.     else {
  402.         BP_DebugString("Document_DoPick: Q3View_StartPicking failed.");
  403.     }
  404.  
  405.     return numHits;
  406. }
  407.  
  408. /*    --------------------------------------------------------------------
  409. **    Document_NewPick
  410. **    Creates a new pick object. pWPPData->point is assumed to be initialized.
  411. */
  412. static
  413. TQ3PickObject Document_NewPick(
  414.     TQ3WindowPointPickData    *pWPPData)
  415. {
  416.     if (pWPPData == NULL) {
  417.         return NULL;
  418.     }
  419.  
  420.     /* Create the window point pick */
  421.     pWPPData->data.sort                 = kQ3PickSortNearToFar;
  422.     pWPPData->data.numHitsToReturn    = kQ3ReturnAllHits;
  423.     /*    We want all this info    */
  424.     pWPPData->data.mask             =    kQ3PickDetailMaskObject |
  425.                                         kQ3PickDetailMaskPath;
  426.     pWPPData->vertexTolerance =
  427.     pWPPData->edgeTolerance   = 3.0;
  428.  
  429.     return (Q3WindowPointPick_New(pWPPData));
  430. }
  431.  
  432. /*----------------------------------------------------------------------*/
  433. /*----------------------------------------------------------------------*/
  434.  
  435.  
  436.  
  437. void Document_DoPickAndRotate( DocumentHdl pDocument)
  438. {
  439.     TQ3WindowPointPickData    wppData;
  440.     TQ3PickObject            pickObject;
  441.     TQ3Status                status = kQ3Failure;
  442.     TQ3GroupObject            theHitGroupObject;        /*    What we hit: it's the group
  443.                                                     holding the hit object    */
  444.     TQ3HitPath                theHitPath;                /*    the group hierarchy    */
  445.     TQ3PickDetail            testDetail;                /*    Used to check if this mask is valid    */
  446.  
  447.     
  448.         assert(pDocument != NULL);
  449.         
  450.         HLock((Handle)pDocument);
  451.  
  452.         Utility_MyGetMouse(&wppData.point);
  453.             /* Create a pick */
  454.         if((pickObject = Document_NewPick(&wppData)) == NULL) {
  455.              BP_DebugString("Document_DrawOnTexture: pickObject == NULL.");
  456.             goto bail;
  457.         }
  458.  
  459.         if (Q3WindowPointPick_SetPoint(pickObject, &wppData.point) == kQ3Failure) {
  460.             goto bail;
  461.         }
  462.  
  463.         if (Document_DoPick(*pDocument, pickObject) != 0) {
  464.         
  465.             /*    HERE'S WHERE ALL THE PICKING TAKES PLACE    */
  466.             
  467.             /*    Get the hit path    */
  468.             if ( Q3Pick_GetPickDetailValidMask( pickObject, 0, &testDetail) == kQ3Success) {
  469.  
  470.                 if ( testDetail & kQ3PickDetailMaskPath) {
  471.  
  472.                     if ( Q3Pick_GetPickDetailData(pickObject, 0, kQ3PickDetailMaskPath, &theHitPath) == kQ3Success) {
  473.  
  474.                         /*    Get the group that holds the hit object    */
  475.                         theHitGroupObject = Utility_GetEnclosingGroup((const TQ3HitPath *)&theHitPath);
  476.  
  477.                         Document_Rotate(pDocument, theHitGroupObject);
  478.  
  479.                         Q3HitPath_EmptyData(&theHitPath);    /*    Empty the hit path    */
  480.  
  481.                         Q3Object_Dispose(theHitGroupObject);
  482.                     }
  483.                 }
  484.             }
  485.             Q3Pick_EmptyHitList(pickObject);    /*    Empty the list    */
  486.         }
  487.  
  488. bail:
  489.  
  490.     if (pickObject != NULL) {
  491.         Q3Object_Dispose(pickObject);
  492.         pickObject = NULL;
  493.     }
  494.  
  495.     HUnlock((Handle)pDocument);
  496.     
  497. }
  498.  
  499.  
  500. /* -------------------------------------------------------------------------------------------
  501. **    
  502. **    
  503. */
  504.  
  505. void    Document_Rotate(DocumentHdl    theDocumentHdl,
  506.                         TQ3GroupObject    theGroup)
  507. {
  508.     TQ3Point2D     newMouse;
  509.     TQ3Point2D    oldPoint;
  510.     float        dx, dy;
  511.     float        width, height;
  512.     float        xRot, yRot;
  513.     DocumentPtr    theDocument;
  514.     TQ3TransformObject transform;
  515.     TQ3Matrix4x4 matrix, newMatrix;
  516.     TQ3BoundingBox viewBBox;
  517.     TQ3Point3D    center;
  518.     TQ3Status status;
  519.  
  520.     
  521.         assert(theDocumentHdl != NULL);
  522.         
  523.         HideCursor();
  524.         
  525.         HLock((Handle)theDocumentHdl);
  526.  
  527.         theDocument = *theDocumentHdl;
  528.         
  529.         Utility_MyGetMouse(&oldPoint);    /*    get the mouse in local co-ordinates,    */ 
  530.                                         /*    local to the  current GrafPort    */
  531.  
  532.         width = theDocument->fWindow->portRect.left - theDocument->fWindow->portRect.right;
  533.         height = theDocument->fWindow->portRect.bottom - theDocument->fWindow->portRect.top;
  534.  
  535.         while (Utility_MyStillDown()) {
  536.         
  537.             Utility_MyGetMouse(&newMouse);    /*    get the mouse in local co-ordinates,    */ 
  538.                                             /*    local to the  current GrafPort    */
  539.  
  540.             dx = oldPoint.y - newMouse.y;
  541.             dy = newMouse.x - oldPoint.x;
  542.             
  543.             if ((dx != 0) || (dy != 0)) {
  544.                 TQ3Matrix4x4        tempMatrix;
  545.                 
  546.                 xRot = ((float) dx * kQ3Pi) / width;
  547.                 yRot = ((float) dy * kQ3Pi) / height;
  548.  
  549.                 if ((xRot != 0.0) || (yRot != 0.0)) {
  550.  
  551.                         /* Get the group's transform */
  552.                     transform = Document_GetGroupTransform(theGroup);
  553.                     if (transform != NULL) {
  554.  
  555.                         /* Change the transform's matrix with the translation */
  556.                         Q3Transform_GetMatrix(transform, &matrix);
  557.  
  558.                         status = GetDocumentGroupBoundingBox( theDocument->fView,
  559.                                                                 theGroup, 
  560.                                                                 &viewBBox);
  561.                         status = ComputeCenterOfBoundingBox(&viewBBox,
  562.                                                             ¢er);
  563.                         Q3Matrix4x4_SetRotateAboutPoint(&tempMatrix, ¢er, xRot, yRot, 0.0);
  564.                         Q3Matrix4x4_Multiply(&matrix, &tempMatrix, &newMatrix);
  565.  
  566.                         Q3MatrixTransform_Set(transform, &newMatrix);
  567.  
  568.                         Document_Draw(theDocument);
  569.                         Q3Object_Dispose(transform);
  570.                     }
  571.                 }
  572.             }
  573.             oldPoint.x = newMouse.x; oldPoint.y = newMouse.y;
  574.         }
  575.  
  576.         ShowCursor();
  577.         
  578.         HUnlock((Handle)theDocumentHdl);
  579.     
  580. }
  581.  
  582. TQ3TransformObject Document_GetGroupTransform(TQ3GroupObject    theGroup)
  583. {
  584.     TQ3TransformObject transform;
  585.     TQ3GroupPosition transformPos;
  586.     TQ3Status status;
  587.  
  588.         /* Get transform's position in this group */
  589.         transformPos = NULL;
  590.         status = Q3Group_GetFirstPositionOfType(theGroup,
  591.                                                 kQ3ShapeTypeTransform,
  592.                                                 &transformPos);
  593.         if ((status == kQ3Success) && (transformPos != NULL)) {
  594.  
  595.             /* Get transform's object reference */
  596.             transform = NULL;
  597.             status = Q3Group_GetPositionObject(theGroup,
  598.                                                 transformPos,
  599.                                                 &transform);
  600.             if ((status == kQ3Success) && (transform != NULL)) {
  601.                 return transform;
  602.             }
  603.         }
  604.     
  605.     return NULL;
  606. }